using System.Collections.Generic;
using System.Data;
using System.Text.RegularExpressions;
using Google.Protobuf;
using Google.Protobuf.Collections;

namespace HuaXianQu.ProtoBuffEx.ToolEditor
{
    public class VariableInfo
    {
        public enum DataType
        {
            /// <summary>
            /// 基础类型
            /// </summary>
            Basic,

            /// <summary>
            /// 自定义类型
            /// </summary>
            Custom,

            /// <summary>
            /// 列表
            /// </summary>
            List,

            /// <summary>
            /// 自定义列表
            /// </summary>
            CustomList,

            /// <summary>
            /// 词典
            /// </summary>
            Dictionary,

            /// <summary>
            /// 自定义词典
            /// </summary>
            CustomDictionary,
        }

        public class ExcelVariableInfoAll
        {
            /// <summary>
            /// 变量名称
            /// </summary>
            public string VariableName;

            /// <summary>
            /// excel定义的变量特性
            /// </summary>
            public MapField<string, ExcelVariableInfoAttribute> ExcelVariableMap = new();
        }

        public class ExcelVariableInfoAttribute
        {
            public bool IsMaKey = false;
            public bool IsPrimaryKey = false;
            public string ExcelMapVariableName;
            public int SortIndex = -1;
            public string ExcelVariableValue;
            public string VariableName;
            public string OriginVariableType;
            public string VariableType;
        }

        public InternalDataCollectionBase ExcelDataOrInfo { get; set; }
        public DataRow ExcelData { get; set; }
        public int DataRowCount { get; set; }
        public string RepeatedName { get; set; }

        /// <summary>
        /// 变量名称
        /// </summary>
        public string VariableName { get; set; }

        /// <summary>
        /// 自定义变量类型
        /// </summary>
        public string CustomVariableName { get; set; }

        /// <summary>
        /// Proto变量对应的编码
        /// </summary>
        public int ProtoIndex { get; set; }

        /// <summary>
        /// 数据类型
        /// </summary>
        public string VariableType { get; set; }

        /// <summary>
        /// 原始变量类型
        /// </summary>

        public string OriginVariableType { get; set; }

        public string ExcelVariableInfo { get; set; }

        public string MapKey { get; set; }

        public bool IsPrimaryKey = false;
        public object PrimaryKey { get; set; }

        /// <summary>
        /// excel对应的数据索引，用于数据绑定
        /// </summary>
        public int DataIndex { get; set; }

        public bool IsReadFirst { get; set; }
        public int MapKeyIndex { get; set; } = -1;

        public int ColumnCount { get; set; }

        public IMessage DataMessage { get; set; }
        private List<VariableInfo> Childs = new();
        private List<VariableInfo> ChildFromClass = new();
        public int LanId { get; set; }
        private ProtoBasicTypeParse _basicTypeParse = new();
        private ProtoListTypeParse _protoListTypeParse = new();
        public DataType CurDataType = DataType.Basic;
        public ExcelVariableInfoAll CurExcelVariableInfoAll { get; set; }
        public bool IsDictionary { get; set; }
        public bool IsLan { get; set; }
        private string countTime;
        public string MemberName { get; set; }
        public VariableInfo Member { get; set; }
        public bool IsMember { get; set; }

        public void SetName(string name)
        {
            Match match = Regex.Match(name, @"^(.*)\.([^\s]*)$");
            if (match.Groups.Count == 3)
            {
                VariableName = match.Groups[1].Value;
                MemberName = match.Groups[2].Value;
                IsMember = true;
                return;
            }

            VariableName = name;
        }

        public bool Parse()
        {
            string protoType = OriginVariableType.Trim();

            //基础类型
            if (_basicTypeParse.ParseType(protoType.ToLower(), out string basicType))
            {
                VariableType = basicType;
                CurDataType = DataType.Basic;
                return true;
            }


            Match match = Regex.Match(protoType, @"^(.*):([^\s]*)$");
            if (match.Groups.Count == 3)
            {
                protoType = match.Groups[1].Value;
                if (string.IsNullOrWhiteSpace(protoType))
                {
                    return false;
                }

                if (match.Groups[2].Value is { Length: > 0 })
                {
                    MapKey = match.Groups[2].Value;
                    if (!string.IsNullOrWhiteSpace(MapKey))
                    {
                        if (int.TryParse(MapKey, out int key))
                        {
                            if (key < 0)
                            {
                                IsReadFirst = true;
                            }
                            else
                            {
                                MapKeyIndex = key;
                            }
                        }
                    }
                }
            }

            //List列表类型
            string data = null;
            match = Regex.Match(protoType, @"^List[\s\t]*<[\s\t]*([\w]+)[\s\t]*>$");
            data = match.Groups[1].Value;
            if (!string.IsNullOrEmpty(data))
            {
                CurDataType = DataType.List;
                RepeatedName = "repeated ";
                if (!_basicTypeParse.ParseType(data, out string dictType))
                {
                    dictType = data;
                    CustomVariableName = data;
                    CurDataType = DataType.CustomList;
                }

                VariableType = dictType;
                return true;
            }

            //match = Regex.Match(protoType, @"Dictionary<([^>]+),([^>]+)>(?::(\w*))?");
            match = Regex.Match(protoType, @"Dictionary[\s\t]*<[\s\t]*([\w]+)[\s\t]*,[\s\t]*([\w]+)[\s\t]*>$");
            if (match.Groups.Count == 3)
            {
                if (!_basicTypeParse.ParseType(match.Groups[1].Value, out string dictType))
                {
                    dictType = match.Groups[1].Value;
                }

                CurDataType = DataType.Dictionary;
                if (!_basicTypeParse.ParseType(match.Groups[2].Value, out string dictValueType))
                {
                    dictValueType = match.Groups[2].Value;
                    CustomVariableName = dictValueType;
                    CurDataType = DataType.CustomDictionary;
                }

                VariableType = $"map<{dictType},{dictValueType}>";
                return true;
            }

            CurDataType = DataType.Custom;
            CustomVariableName = protoType;
            VariableType = protoType;
            return true;
        }

        public void ParseExcelVariableInfo()
        {
            if (string.IsNullOrEmpty(ExcelVariableInfo))
            {
                return;
            }

            string variableNameTemp = ExcelVariableInfo.Trim();
            Match match = Regex.Match(variableNameTemp, @"{([\w\W]+)}");
            if (match.Groups.Count != 2)
            {
                return;
            }

            variableNameTemp = match.Groups[1].Value;
            MatchCollection matchs = Regex.Matches(variableNameTemp, @"([^:;,]*);*([^:;,]*):([^:;,]*),*");
            if (matchs.Count == 0)
            {
                return;
            }

            CurExcelVariableInfoAll = new ExcelVariableInfoAll()
            {
                VariableName = VariableName,
            };
            for (int i = 0; i < matchs.Count; i++)
            {
                Match temp = matchs[i];
                if (temp.Groups.Count == 4)
                {
                    ExcelVariableInfoAttribute excelVariableInfoAttribute = new ExcelVariableInfoAttribute()
                    {
                        VariableName = VariableName,
                        VariableType = VariableType,
                        OriginVariableType = OriginVariableType,
                    };
                    string keyMap = temp.Groups[1].Value;
                    if (keyMap == "key")
                    {
                        excelVariableInfoAttribute.IsMaKey = true;

                        variableNameTemp = temp.Groups[2].Value;
                        if (string.IsNullOrEmpty(variableNameTemp))
                        {
                            excelVariableInfoAttribute.IsPrimaryKey = true;
                            excelVariableInfoAttribute.ExcelMapVariableName = "key";
                        }
                        else
                        {
                            if (int.TryParse(temp.Groups[3].Value, out int index))
                            {
                                excelVariableInfoAttribute.SortIndex = index;
                            }

                            excelVariableInfoAttribute.ExcelVariableValue = temp.Groups[3].Value;
                            excelVariableInfoAttribute.ExcelMapVariableName = variableNameTemp;
                        }
                    }
                    // else if (keyMap == "lan")
                    // {
                    //     excelVariableInfoAttribute.ExcelMapVariableName = keyMap;
                    //     excelVariableInfoAttribute.ExcelVariableValue = temp.Groups[3].Value;
                    // }
                    else
                    {
                        excelVariableInfoAttribute.ExcelMapVariableName = keyMap;
                        excelVariableInfoAttribute.ExcelVariableValue = temp.Groups[3].Value;
                    }

                    CurExcelVariableInfoAll.ExcelVariableMap.Add(excelVariableInfoAttribute.ExcelMapVariableName,
                        excelVariableInfoAttribute);
                }
            }
        }

        public void AddChild(VariableInfo info)
        {
            info.Member = this;
            Childs.Add(info);
        }

        public void GetClassInfo(ref List<VariableInfo> infos)
        {
            if (ChildFromClass.Count > 0)
            {
                infos.Add(this);
                foreach (var child in ChildFromClass)
                {
                    child.GetClassInfo(ref infos);
                }
            }
        }

        public bool IsExistsCustomClass()
        {
            return CurDataType==DataType.Custom || CurDataType==DataType.CustomDictionary || CurDataType==DataType.CustomList;
        }

        public override string ToString()
        {
            return $"  {RepeatedName}{VariableType} {VariableName} = {ProtoIndex};";
        }
    }
}